package avl.sv.client;

import avl.sv.server.slides.Slides;
import avl.sv.shared.ImageID;
import avl.sv.shared.SlideSet;
import avl.sv.shared.SlideSets;
import avl.sv.shared.sources.SlideSource;
import avl.sv.shared.sources.SlideSourceFile;
import avl.tiff.TiffDirectory;
import avl.tiff.TiffFile;
import ij.gui.MessageDialog;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListModel;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.ListCellRenderer;
import javax.swing.ProgressMonitor;
import javax.swing.SwingUtilities;
import javax.swing.filechooser.FileFilter;
import javax.xml.ws.WebServiceException;

/**
 *
 * @author benbryan
 */
public class UploadSlideFrame extends javax.swing.JDialog {
    private String authToken;
    private final static int NUMEL_THREADS = 5;
    AtomicInteger uploadCounter = new AtomicInteger();
    SlideSet CREATE_NEW =  new SlideSet("Create New");
    private boolean errorsOccured;
    public UploadSlideFrame(java.awt.Frame parent) {
        super(parent, false);
        initComponents();
        jFileChooserImage.setApproveButtonText("Upload");
        jFileChooserImage.setFileFilter(new FileFilter() {
            String validExt[] = {"bmp", "gif", "png", "jpg", "jpeg", "svs"};

            @Override
            public boolean accept(File f) {
                if (f.isDirectory()) {
                    return true;
                }
                String ext = getFileExtension(f);
                for (int i = 0; i < validExt.length; i++) {
                    if (ext.equalsIgnoreCase(validExt[i])) {
                        return true;
                    }
                }
                return false;
            }

            @Override
            public String getDescription() {
                return "*.bmp;*.gif;*.png;*.jpg;*.jpeg;*.svs;";
            }
        });
    }
    
    private class ImageFileRef {
        final File original; 
        File converted = null;
        boolean compatable = false;
        public ImageFileRef(File original) {
            this.original = original;
        }
        
    }
    
    @Override
    public void setVisible(boolean b) {
        if (b){
            SlideSets slideSets = AdvancedVirtualMicroscope.getSlideSets();
            jComboBoxImageSets.removeAllItems();
            for (SlideSet slideSet:slideSets.getSlideSets()){
                jComboBoxImageSets.addItem(slideSet);
            }
            if (jComboBoxImageSets.getComponents().length == 0){
                jComboBoxImageSets.addItem(new SlideSet("default"));
            }
            jComboBoxImageSets.addItem(CREATE_NEW);

            jListSelectedImages.setModel(new DefaultListModel<ImageFileRef>());
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    jFileChooserImage.showDialog(getThis(), "Select");
                }
            });
        } else {
            for (int i = 0; i < jListSelectedImages.getModel().getSize(); i++) {
                final ImageFileRef imageFileRef = jListSelectedImages.getModel().getElementAt(i);
                if (imageFileRef.converted != null) {
                    imageFileRef.converted.delete();
                }
            }
        }
        super.setVisible(b); 
    }
    private Dialog getThis(){
        return this;
    }
    
    public void uploadImageFile(ProgressMonitor pm, File toUpload, String slideSetName, String slideName){
        
        String result = uploadSVS(pm, slideSetName, slideName, toUpload);
        if (result.startsWith("error:")){
            final String msg = result + "\n" + "while uploading slide " + slideName + " in slideSet " + slideSetName;
            errorsOccured = true;
            AdvancedVirtualMicroscope.setStatusText(msg, 5000);
        }

        pm.close();
    }
    
    public String uploadSVS(ProgressMonitor pm, String slideSetName, String slideName, File file) {
        String result;

        Slides slidePort = AdvancedVirtualMicroscope.getSlidesPort();
        authToken = slidePort.slidePostInit(slideSetName, slideName, ImageID.get(file));
        if (authToken.startsWith("error")){
            return authToken;
        }
        try {
            final ArrayList<TiffDirectory> tds = TiffFile.getTiffDirectories(file);
            for (int dirIdx = 0; dirIdx < tds.size(); dirIdx++) {
                pm.setNote( file.getName() + " Directory " + String.valueOf(dirIdx + 1) + " of " + String.valueOf(tds.size()));
                pm.setProgress(0);
                final TiffDirectory dir = tds.get(dirIdx);
                
                Properties props = dir.getProperties();
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                props.storeToXML(new BufferedOutputStream(bos), null);
                bos.flush();
                String propsXML = bos.toString();
                result = slidePort.slidePostSetupDirectory(authToken, dirIdx, propsXML);
                if (result.startsWith("error")){
                    slidePort.slidePostFinalize(authToken, true);
                    return result;
                }
                
                pm.setMaximum((int) ((dir.getTilesAcrossW() * dir.getTilesDownL()) + 1));
                
                ArrayList<UploadElement> toUpload = new ArrayList<>();
                for (int x = 0; x < dir.getTilesAcrossW(); x++) {
                    for (int y = 0; y < dir.getTilesDownL(); y++) {
                        toUpload.add(new UploadElement(pm, dir, dirIdx, x, y));                        
                    }
                }
                try {
                    ExecutorService pool = Executors.newFixedThreadPool(NUMEL_THREADS);
                    uploadCounter.set(0);
                    List<Future<Boolean>> resultPool = pool.invokeAll(toUpload);
                    pool.shutdown();
                    boolean executionFinished = false;
                    for (int iter = 0; iter < 3; iter++){
                        executionFinished = pool.awaitTermination(1, TimeUnit.SECONDS);  
                        if (pm.isCanceled()){
                            slidePort.slidePostFinalize(authToken, true);
                            return "upload cancelled";
                        }
                        if (executionFinished){
                            ArrayList<UploadElement> toUploadAgain = new ArrayList<>();
                            for (int i = 0; i < resultPool.size(); i++) {
                                boolean uploaded = resultPool.get(i).get();
                                if (!uploaded) {
                                    toUploadAgain.add(toUpload.get(i));
                                }
                            }
                            if (toUploadAgain.isEmpty()){
                                break;
                            }
                            toUpload = toUploadAgain;
                            pool = Executors.newFixedThreadPool(NUMEL_THREADS);
                            resultPool = pool.invokeAll(toUpload);
                            pool.shutdown();
                        }                        
                    }
                    if (!executionFinished){
                        slidePort.slidePostFinalize(authToken, true);
                        return "error: processes timeout during upload";
                    }
                } catch ( InterruptedException | ExecutionException ex) {
                    slidePort.slidePostFinalize(authToken, true);
                    Logger.getLogger(UploadSlideFrame.class.getName()).log(Level.SEVERE, null, ex);
                    return "error: somthing failed during upload";
                }
            }
        } catch (IOException ex) {
            Logger.getLogger(UploadSlideFrame.class.getName()).log(Level.SEVERE, null, ex);
            slidePort.slidePostFinalize(authToken, true);
            return "error: somthing failed during upload";
        }
        slidePort.slidePostFinalize(authToken, false);
        return "slide uploaded";
    }
            
    private class UploadElement implements Callable<Boolean>{
        private TiffDirectory dir;
        private int dirIdx, x, y;
        ProgressMonitor pm;

        public UploadElement(ProgressMonitor pm, TiffDirectory dir, int dirIdx, int x, int y) {
            this.pm = pm;
            this.dir = dir;
            this.dirIdx = dirIdx;
            this.x = x;
            this.y = y;
        }
        
        @Override
        public Boolean call() throws Exception {
            //return true if successfull
            Slides slidePort = AdvancedVirtualMicroscope.getSlidesPort();
            try {
                byte img[] = dir.getTileAsByteArray(x, y);
                String result = slidePort.slidePostTile(authToken, dirIdx, x, y, img);
                if (result.startsWith("error")){
                    System.err.println(result);
                    return false;
                }
            } catch ( WebServiceException | IOException ex ){
                return false;
            }
            int progress = uploadCounter.incrementAndGet();
            pm.setProgress(progress);
            return true;
        }

    }
    
    private static String getFileExtension(File file){
        String extension = "";
        int i = file.getName().lastIndexOf('.');
        if (i > 0) {
            extension = file.getName().substring(i+1);
        }
        return extension;
    }
    
//    public static void main(final String args[]) {
//        File input = new File("C:\\Users\\benbryan\\Desktop\\New folder\\input.jpg");
//        File output = convertToSVS_StyleTiff(input, 0.95f);
//        output = null;
//    }

    private File convertToSVS_StyleTiff(File originalImg, float jpegQuality) {
        FileOutputStream fos;
        File tempImg;
        ProgressMonitor pm = new ProgressMonitor(this, "Converting image", "", 0, 100);
        try {
            tempImg = new File("./"+ originalImg.getName() + ".tif");
            tempImg.createNewFile();
            fos = new FileOutputStream(tempImg);
            int tileSize = 256;
            pm.setNote("Reading original image");
            pm.setProgress(5);
            BufferedImage originalImage = ImageIO.read(originalImg);
            if (originalImage == null){
                return null;
            }
            TiffWriter.write(pm, originalImage, fos, tileSize, jpegQuality);
            fos.close();
        } catch (IOException ex) {
            Logger.getLogger(UploadSlideFrame.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        } 
        pm.close();
        return tempImg;
    }
    
    private void checkJPEG_Quality(){
        int v = 0;
        try {
            v = Integer.parseInt(jTextFieldJPEG_Quality.getText());
        } catch (Exception ex){
            
        }
        if (v <= 0) {
            v = 75;
        } else if (v > 100){
            v = 100;
        }
        jTextFieldJPEG_Quality.setText(String.valueOf(v));
    }

    private Frame getParentFrame(){
        Object obj = SwingUtilities.getWindowAncestor(this);
        if (obj instanceof Frame){
            return (Frame) obj;
        } else {
            return null;
        }
    }
        
    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jFileChooserImage = new javax.swing.JFileChooser();
        jTextFieldJPEG_Quality = new javax.swing.JTextField();
        jLabel5 = new javax.swing.JLabel();
        jComboBoxImageSets = new javax.swing.JComboBox<SlideSet>();
        jLabel1 = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        jListSelectedImages = new javax.swing.JList<ImageFileRef>();
        jLabel2 = new javax.swing.JLabel();
        jButtonStartUpload = new javax.swing.JButton();
        jButtonConvertImages = new javax.swing.JButton();
        jPanel1 = new javax.swing.JPanel();
        jScrollPane2 = new javax.swing.JScrollPane();
        jTextArea1 = new javax.swing.JTextArea();

        jFileChooserImage.setMultiSelectionEnabled(true);
        jFileChooserImage.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jFileChooserImageActionPerformed(evt);
            }
        });

        setTitle("Upload slides to server");

        jTextFieldJPEG_Quality.setText("75");
        jTextFieldJPEG_Quality.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jTextFieldJPEG_QualityActionPerformed(evt);
            }
        });
        jTextFieldJPEG_Quality.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                jTextFieldJPEG_QualityFocusLost(evt);
            }
        });

        jLabel5.setText("JPEG Quality");

        jComboBoxImageSets.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jComboBoxImageSetsActionPerformed(evt);
            }
        });

        jLabel1.setText("Target Image Set");

        jListSelectedImages.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jListSelectedImagesMouseClicked(evt);
            }
        });
        jScrollPane1.setViewportView(jListSelectedImages);

        jLabel2.setText("Images to Upload");

        jButtonStartUpload.setText("Upload Selected Images");
        jButtonStartUpload.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonStartUploadActionPerformed(evt);
            }
        });

        jButtonConvertImages.setText("Convert Images");
        jButtonConvertImages.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonConvertImagesActionPerformed(evt);
            }
        });

        jTextArea1.setColumns(20);
        jTextArea1.setFont(new java.awt.Font("Monospaced", 0, 12)); // NOI18N
        jTextArea1.setRows(5);
        jTextArea1.setText("How to upload images:\n\nSome images may be directly compatible with AVM.  Those images are highlighted \nin GREEN and are ready for upload.  Incompatible image formats are highlighted \nin RED and require conversion (to a temporary file) before upload. \n\nClicking on the \"Convert Images\" button will attempt to convert incompatible \nimages to a compatible format by recompressing them as Tiled JPEG in TIFF \nimages using the specified JPEG Quality parameter.  If successful the image \nwill be highlighted in GREEN and ready for upload.\n \nDouble clicking on an image name in GREEN will attempt to open the image \nin AVM.  If you can open it from here, then it should work on the server.  \nThis should be used for testing images before upload.   \n");
        jScrollPane2.setViewportView(jTextArea1);

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 565, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 0, Short.MAX_VALUE))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane2)
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jComboBoxImageSets, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jLabel1)
                    .addComponent(jLabel2)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                            .addComponent(jButtonStartUpload, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jButtonConvertImages, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jTextFieldJPEG_Quality, javax.swing.GroupLayout.PREFERRED_SIZE, 47, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jLabel5))
                    .addComponent(jScrollPane1))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jComboBoxImageSets, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jLabel2)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 138, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jButtonConvertImages)
                    .addComponent(jTextFieldJPEG_Quality, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel5))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButtonStartUpload)
                .addContainerGap())
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents
    
    private void jTextFieldJPEG_QualityActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jTextFieldJPEG_QualityActionPerformed
        checkJPEG_Quality();
    }//GEN-LAST:event_jTextFieldJPEG_QualityActionPerformed

    private void jTextFieldJPEG_QualityFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_jTextFieldJPEG_QualityFocusLost
        checkJPEG_Quality();
    }//GEN-LAST:event_jTextFieldJPEG_QualityFocusLost

    private void jFileChooserImageActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jFileChooserImageActionPerformed
        
        if (!evt.getActionCommand().equals(JFileChooser.APPROVE_SELECTION)){
            setVisible(false);
            return;
        }

        final File files[] = jFileChooserImage.getSelectedFiles();
        if (files.length == 0){
            setVisible(false);
            return;
        }
        ImageFileRef imgRefs[] = new ImageFileRef[files.length];
        for (int i = 0; i < files.length; i++){
            imgRefs[i] = new ImageFileRef(files[i]);
            if (getFileExtension(imgRefs[i].original).equalsIgnoreCase("SVS")){
                imgRefs[i].compatable = true;
            }
        }

        jListSelectedImages.setModel(new DefaultComboBoxModel<>(imgRefs));
        jListSelectedImages.setCellRenderer(new ImageListCellRenderer());
        
    }//GEN-LAST:event_jFileChooserImageActionPerformed

    class ImageListCellRenderer extends JLabel implements ListCellRenderer<ImageFileRef> {

        public ImageListCellRenderer() {
            setOpaque(true);
        }

        @Override
        public Component getListCellRendererComponent(JList<? extends ImageFileRef> list, ImageFileRef imgFileRef, int index, boolean isSelected, boolean cellHasFocus) {
            
            setText(imgFileRef.original.getName());

            Color background;
            Color foreground;
            
            if (isSelected) {
                background = Color.BLUE;
                foreground = Color.WHITE;
            } else if (imgFileRef.compatable){
                background = Color.GREEN;
                foreground = Color.WHITE;
            } else {
                background = Color.RED;
                foreground = Color.WHITE;
            }

            setBackground(background);
            setForeground(foreground);

            return this;
        }

    }
        
    String newImageSetName = "";
    private void jComboBoxImageSetsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jComboBoxImageSetsActionPerformed
        if ((jComboBoxImageSets.getSelectedItem() != null) && (jComboBoxImageSets.getSelectedItem().equals(CREATE_NEW))) {
            String temp = JOptionPane.showInputDialog(this, "Enter New Image Set Name: ", newImageSetName);
            if (temp == null){
                jComboBoxImageSets.setSelectedIndex(0);
                return;
            }
            newImageSetName = temp;
            for (byte b:newImageSetName.getBytes()){
                if ((b < 48) || (b>122) || ((b>57)&&(b<65)) || ((b>90)&&(b<97)) ){
                    JOptionPane.showMessageDialog(this, "Invalid Name\nName must contain alphanumeric characters only");
                    jComboBoxImageSets.setSelectedIndex(0);
                    return;
                }
            }
            SlideSet newItem = new SlideSet(newImageSetName);
            jComboBoxImageSets.addItem(newItem);
            jComboBoxImageSets.setSelectedItem(newItem);
        }
        
    }//GEN-LAST:event_jComboBoxImageSetsActionPerformed

    private void jButtonStartUploadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonStartUploadActionPerformed
        final Frame superFrame = getParentFrame();
        if (jListSelectedImages.getSelectedValuesList().size() == 0){
            new MessageDialog(getParentFrame(), "Error", "Select images for upload first");
            return;
        }
        Executors.newSingleThreadExecutor().submit(new Runnable() {
            @Override
            public void run() {
                try{
                errorsOccured = false;
                final long startTime = new Date().getTime();
                final SlideSet slideSet = ((SlideSet) jComboBoxImageSets.getSelectedItem());
                ProgressMonitor pm = new ProgressMonitor(superFrame, "Uploading Slide(s)", "Starting...", 0, 100);
                pm.setMillisToDecideToPopup(100);
                pm.setMillisToPopup(500);
                for (final ImageFileRef imageFileRef:jListSelectedImages.getSelectedValuesList()) {
                    if (imageFileRef.compatable) {
                        if (imageFileRef.converted != null){
                            uploadImageFile(pm, imageFileRef.converted, slideSet.getSlideSetName(), imageFileRef.original.getName());
                        } else {
                            uploadImageFile(pm, imageFileRef.original, slideSet.getSlideSetName(), imageFileRef.original.getName());
                        }
                    } 
                }
                pm.close();
                if ((new Date().getTime() - startTime) > 2000) {
                    Toolkit.getDefaultToolkit().beep();
                }
                AdvancedVirtualMicroscope.getInstance().updateSlideSetTree();
                if (errorsOccured){
                    int result = JOptionPane.showConfirmDialog(superFrame, "Problems occurred during upload\nOpen log?", "Error", JOptionPane.YES_NO_OPTION);
                    if (result == JOptionPane.YES_OPTION){
                        AdvancedVirtualMicroscope.showLogWindow();
                    }
                }
                errorsOccured = false;
                                } catch (Exception ex){
                    Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }//GEN-LAST:event_jButtonStartUploadActionPerformed

    private void jButtonConvertImagesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonConvertImagesActionPerformed
        Executors.newSingleThreadExecutor().submit(new Runnable() {
            @Override
            public void run() {
                try {
                    final long startTime = new Date().getTime();
                    ProgressMonitor pm = new ProgressMonitor(getThis(), "Converting images", "", 0, 100);
                    for (int i = 0; i < jListSelectedImages.getModel().getSize(); i++) {
                        final ImageFileRef imageFileRef = jListSelectedImages.getModel().getElementAt(i);
                        if (!imageFileRef.compatable) {
                            try {
                                pm.setMaximum(10);
                                pm.setMaximum(2);
                                pm.setNote("Converting image...");
                                File tempImg = convertToSVS_StyleTiff(imageFileRef.original, Float.valueOf(jTextFieldJPEG_Quality.getText()) / 100);
                                if (tempImg == null) {
                                    AdvancedVirtualMicroscope.setStatusText("Error: Failed to convert image " + imageFileRef.original.toString() + "to server required format", 5000);
                                    return;
                                }
                                imageFileRef.converted = tempImg;
                                imageFileRef.compatable = true;
                            } catch (Exception ex) {
                                Logger.getLogger(UploadSlideFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
                            } finally {
                                jListSelectedImages.updateUI();
                            }
                        }
                    }
                } catch (Exception ex){
                    Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }//GEN-LAST:event_jButtonConvertImagesActionPerformed

    private void jListSelectedImagesMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jListSelectedImagesMouseClicked
        if (evt.getClickCount() != 2) {
            return;
        }
        try {
            ImageFileRef imageFileRef = jListSelectedImages.getSelectedValue();
            if (imageFileRef == null) {
                return;
            }
            if (imageFileRef.compatable) {
                SlideSource slideSource;
                if (imageFileRef.converted != null) {
                    slideSource = new SlideSourceFile(imageFileRef.converted);
                } else {
                    slideSource = new SlideSourceFile(imageFileRef.original);
                }
                AdvancedVirtualMicroscope.addSlideViewer(slideSource);
            }
        } catch (IOException ex) {
            Logger.getLogger(AdvancedVirtualMicroscope.class.getName()).log(Level.SEVERE, null, ex);
        }
    }//GEN-LAST:event_jListSelectedImagesMouseClicked
        
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButtonConvertImages;
    private javax.swing.JButton jButtonStartUpload;
    private javax.swing.JComboBox<SlideSet> jComboBoxImageSets;
    private javax.swing.JFileChooser jFileChooserImage;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JList<ImageFileRef> jListSelectedImages;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JTextArea jTextArea1;
    private javax.swing.JTextField jTextFieldJPEG_Quality;
    // End of variables declaration//GEN-END:variables
}
